#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
布局管理器模块
提供可拖拽的界面布局自定义功能
"""

import json
import os
from PyQt6.QtWidgets import (
    QWidget, QVBoxLayout, QHBoxLayout, QDialog, 
    QListWidget, QPushButton, QLabel, QSplitter,
    QComboBox, QCheckBox, QSpinBox, QGroupBox,
    QDockWidget, QMainWindow, QTabWidget, QFrame
)
from PyQt6.QtGui import QAction
from PyQt6.QtCore import Qt, QObject, pyqtSignal, QRect, QPoint, QSize
from PyQt6.QtGui import QDragEnterEvent, QDropEvent, QDragMoveEvent

class DraggableWidget(QFrame):
    """可拖拽的组件"""
    
    # 信号定义
    widget_moved = pyqtSignal(str, QPoint)  # 组件移动信号
    widget_resized = pyqtSignal(str, QSize)  # 组件大小改变信号
    
    def __init__(self, widget_id, title, content_widget=None):
        super().__init__()
        self.widget_id = widget_id
        self.title = title
        self.content_widget = content_widget
        self.is_dragging = False
        self.drag_start_position = QPoint()
        
        self.setup_ui()
        self.setAcceptDrops(True)
    
    def setup_ui(self):
        """设置UI"""
        self.setFrameStyle(QFrame.Shape.Box)
        self.setLineWidth(1)
        
        layout = QVBoxLayout(self)
        
        # 标题栏
        title_frame = QFrame()
        title_frame.setFixedHeight(30)
        title_frame.setStyleSheet("""
            QFrame {
                background-color: #e0e0e0;
                border-bottom: 1px solid #c0c0c0;
            }
        """)
        
        title_layout = QHBoxLayout(title_frame)
        title_layout.setContentsMargins(5, 0, 5, 0)
        
        title_label = QLabel(self.title)
        title_label.setStyleSheet("font-weight: bold;")
        title_layout.addWidget(title_label)
        title_layout.addStretch()
        
        layout.addWidget(title_frame)
        
        # 内容区域
        if self.content_widget:
            layout.addWidget(self.content_widget)
        else:
            placeholder = QLabel(f"内容区域: {self.title}")
            placeholder.setAlignment(Qt.AlignmentFlag.AlignCenter)
            placeholder.setStyleSheet("color: #888888;")
            layout.addWidget(placeholder)
    
    def mousePressEvent(self, event):
        """鼠标按下事件"""
        if event.button() == Qt.MouseButton.LeftButton:
            self.is_dragging = True
            self.drag_start_position = event.globalPosition().toPoint() - self.frameGeometry().topLeft()
        super().mousePressEvent(event)
    
    def mouseMoveEvent(self, event):
        """鼠标移动事件"""
        if self.is_dragging and event.buttons() == Qt.MouseButton.LeftButton:
            new_pos = event.globalPosition().toPoint() - self.drag_start_position
            self.move(new_pos)
            self.widget_moved.emit(self.widget_id, new_pos)
        super().mouseMoveEvent(event)
    
    def mouseReleaseEvent(self, event):
        """鼠标释放事件"""
        if event.button() == Qt.MouseButton.LeftButton:
            self.is_dragging = False
        super().mouseReleaseEvent(event)
    
    def resizeEvent(self, event):
        """大小改变事件"""
        super().resizeEvent(event)
        self.widget_resized.emit(self.widget_id, event.size())

class LayoutManager(QObject):
    """布局管理器"""
    
    # 信号定义
    layout_changed = pyqtSignal(str)  # 布局改变信号
    
    def __init__(self, main_window):
        super().__init__()
        self.main_window = main_window
        self.config_file = os.path.join(os.path.expanduser("~"), ".gofile", "layout_config.json")
        
        # 确保配置目录存在
        os.makedirs(os.path.dirname(self.config_file), exist_ok=True)
        
        # 布局配置
        self.layouts = {
            "default": {
                "name": "默认布局",
                "description": "标准的文件浏览器布局",
                "config": {
                    "splitter_sizes": [200, 600],
                    "dock_positions": {},
                    "widget_positions": {},
                    "widget_sizes": {}
                }
            },
            "dual_pane": {
                "name": "双面板布局",
                "description": "左右双面板文件浏览布局",
                "config": {
                    "splitter_sizes": [400, 400],
                    "dock_positions": {},
                    "widget_positions": {},
                    "widget_sizes": {}
                }
            },
            "media_focus": {
                "name": "媒体焦点布局",
                "description": "专注于媒体播放的布局",
                "config": {
                    "splitter_sizes": [150, 650],
                    "dock_positions": {},
                    "widget_positions": {},
                    "widget_sizes": {}
                }
            }
        }
        
        self.current_layout = "default"
        self.dock_widgets = {}  # 存储停靠窗口
        self.draggable_widgets = {}  # 存储可拖拽组件
        
        # 加载布局配置
        self.load_layout_config()
    
    def create_dock_widget(self, widget_id, title, content_widget, area=Qt.DockWidgetArea.LeftDockWidgetArea):
        """创建停靠窗口"""
        dock = QDockWidget(title, self.main_window)
        dock.setWidget(content_widget)
        dock.setAllowedAreas(
            Qt.DockWidgetArea.LeftDockWidgetArea | 
            Qt.DockWidgetArea.RightDockWidgetArea | 
            Qt.DockWidgetArea.TopDockWidgetArea | 
            Qt.DockWidgetArea.BottomDockWidgetArea
        )
        
        # 连接信号
        dock.dockLocationChanged.connect(lambda area: self.on_dock_moved(widget_id, area))
        dock.topLevelChanged.connect(lambda floating: self.on_dock_floating_changed(widget_id, floating))
        
        self.main_window.addDockWidget(area, dock)
        self.dock_widgets[widget_id] = dock
        
        return dock
    
    def create_draggable_widget(self, widget_id, title, content_widget=None):
        """创建可拖拽组件"""
        widget = DraggableWidget(widget_id, title, content_widget)
        
        # 连接信号
        widget.widget_moved.connect(lambda wid, pos: self.on_widget_moved(wid, pos))
        widget.widget_resized.connect(lambda wid, size: self.on_widget_resized(wid, size))
        
        self.draggable_widgets[widget_id] = widget
        
        return widget
    
    def on_dock_moved(self, widget_id, area):
        """停靠窗口移动事件"""
        if self.current_layout in self.layouts:
            self.layouts[self.current_layout]["config"]["dock_positions"][widget_id] = int(area)
            self.save_layout_config()
            self.layout_changed.emit(self.current_layout)
    
    def on_dock_floating_changed(self, widget_id, floating):
        """停靠窗口浮动状态改变事件"""
        if self.current_layout in self.layouts:
            dock_config = self.layouts[self.current_layout]["config"]["dock_positions"]
            if widget_id not in dock_config:
                dock_config[widget_id] = {}
            dock_config[widget_id]["floating"] = floating
            self.save_layout_config()
    
    def on_widget_moved(self, widget_id, position):
        """可拖拽组件移动事件"""
        if self.current_layout in self.layouts:
            self.layouts[self.current_layout]["config"]["widget_positions"][widget_id] = {
                "x": position.x(),
                "y": position.y()
            }
            self.save_layout_config()
    
    def on_widget_resized(self, widget_id, size):
        """可拖拽组件大小改变事件"""
        if self.current_layout in self.layouts:
            self.layouts[self.current_layout]["config"]["widget_sizes"][widget_id] = {
                "width": size.width(),
                "height": size.height()
            }
            self.save_layout_config()
    
    def apply_layout(self, layout_id):
        """应用指定布局"""
        if layout_id not in self.layouts:
            return False
        
        try:
            layout_config = self.layouts[layout_id]["config"]
            
            # 应用分割器大小
            if hasattr(self.main_window, 'splitter') and "splitter_sizes" in layout_config:
                self.main_window.splitter.setSizes(layout_config["splitter_sizes"])
            
            # 应用停靠窗口位置
            for widget_id, area_info in layout_config.get("dock_positions", {}).items():
                if widget_id in self.dock_widgets:
                    dock = self.dock_widgets[widget_id]
                    if isinstance(area_info, int):
                        area = Qt.DockWidgetArea(area_info)
                        self.main_window.addDockWidget(area, dock)
                    elif isinstance(area_info, dict):
                        if "floating" in area_info:
                            dock.setFloating(area_info["floating"])
            
            # 应用可拖拽组件位置和大小
            for widget_id, pos_info in layout_config.get("widget_positions", {}).items():
                if widget_id in self.draggable_widgets:
                    widget = self.draggable_widgets[widget_id]
                    widget.move(pos_info["x"], pos_info["y"])
            
            for widget_id, size_info in layout_config.get("widget_sizes", {}).items():
                if widget_id in self.draggable_widgets:
                    widget = self.draggable_widgets[widget_id]
                    widget.resize(size_info["width"], size_info["height"])
            
            self.current_layout = layout_id
            self.save_layout_config()
            self.layout_changed.emit(layout_id)
            
            return True
        except Exception as e:
            print(f"应用布局失败: {e}")
            return False
    
    def save_current_layout_as(self, layout_id, name, description):
        """保存当前布局为新布局"""
        try:
            # 获取当前状态
            config = {
                "splitter_sizes": [],
                "dock_positions": {},
                "widget_positions": {},
                "widget_sizes": {}
            }
            
            # 保存分割器大小
            if hasattr(self.main_window, 'splitter'):
                config["splitter_sizes"] = self.main_window.splitter.sizes()
            
            # 保存停靠窗口位置
            for widget_id, dock in self.dock_widgets.items():
                area = self.main_window.dockWidgetArea(dock)
                config["dock_positions"][widget_id] = {
                    "area": int(area),
                    "floating": dock.isFloating()
                }
            
            # 保存可拖拽组件位置和大小
            for widget_id, widget in self.draggable_widgets.items():
                pos = widget.pos()
                size = widget.size()
                config["widget_positions"][widget_id] = {
                    "x": pos.x(),
                    "y": pos.y()
                }
                config["widget_sizes"][widget_id] = {
                    "width": size.width(),
                    "height": size.height()
                }
            
            # 保存布局
            self.layouts[layout_id] = {
                "name": name,
                "description": description,
                "config": config
            }
            
            self.save_layout_config()
            return True
        except Exception as e:
            print(f"保存布局失败: {e}")
            return False
    
    def delete_layout(self, layout_id):
        """删除布局"""
        if layout_id in ["default", "dual_pane", "media_focus"]:
            return False  # 不能删除内置布局
        
        if layout_id in self.layouts:
            del self.layouts[layout_id]
            if self.current_layout == layout_id:
                self.apply_layout("default")
            self.save_layout_config()
            return True
        return False
    
    def get_available_layouts(self):
        """获取可用布局列表"""
        return [(layout_id, layout_data["name"], layout_data["description"]) 
                for layout_id, layout_data in self.layouts.items()]
    
    def get_current_layout(self):
        """获取当前布局"""
        return self.current_layout
    
    def reset_to_default(self):
        """重置为默认布局"""
        return self.apply_layout("default")
    
    def save_layout_config(self):
        """保存布局配置"""
        try:
            config = {
                "current_layout": self.current_layout,
                "layouts": self.layouts
            }
            with open(self.config_file, 'w', encoding='utf-8') as f:
                json.dump(config, f, ensure_ascii=False, indent=2)
        except Exception as e:
            print(f"保存布局配置失败: {e}")
    
    def load_layout_config(self):
        """加载布局配置"""
        try:
            if os.path.exists(self.config_file):
                with open(self.config_file, 'r', encoding='utf-8') as f:
                    config = json.load(f)
                    self.current_layout = config.get("current_layout", "default")
                    # 合并保存的布局配置
                    saved_layouts = config.get("layouts", {})
                    for layout_id, layout_data in saved_layouts.items():
                        if layout_id not in self.layouts or layout_id not in ["default", "dual_pane", "media_focus"]:
                            self.layouts[layout_id] = layout_data
        except Exception as e:
            print(f"加载布局配置失败: {e}")
            self.current_layout = "default"
    
    def export_layout(self, layout_id, file_path):
        """导出布局配置"""
        if layout_id not in self.layouts:
            return False
        
        try:
            layout_data = self.layouts[layout_id]
            with open(file_path, 'w', encoding='utf-8') as f:
                json.dump(layout_data, f, ensure_ascii=False, indent=2)
            return True
        except Exception as e:
            print(f"导出布局失败: {e}")
            return False
    
    def import_layout(self, layout_id, file_path):
        """导入布局配置"""
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                layout_data = json.load(f)
            
            # 验证布局数据格式
            if "name" in layout_data and "config" in layout_data:
                self.layouts[layout_id] = layout_data
                self.save_layout_config()
                return True
            return False
        except Exception as e:
            print(f"导入布局失败: {e}")
            return False
    
    def load_layout(self, name="default"):
        """加载布局配置"""
        try:
            if os.path.exists(self.config_file):
                with open(self.config_file, 'r', encoding='utf-8') as f:
                    self.layouts = json.load(f)
                    
                # 应用默认布局
                if name in self.layouts:
                    self.apply_layout(name)
        except Exception as e:
            print(f"加载布局配置失败: {e}")
    
    def save_layout(self, name="default"):
        """保存当前布局配置"""
        import time
        layout_config = {
            'name': name,
            'timestamp': time.time(),
            'widgets': {}
        }
        
        # 保存主窗口几何信息
        if hasattr(self.main_window, 'geometry'):
            geometry = self.main_window.geometry()
            layout_config['main_window'] = {
                'x': geometry.x(),
                'y': geometry.y(),
                'width': geometry.width(),
                'height': geometry.height()
            }
        
        # 保存各个组件的位置和大小
        for widget_name, widget in self.draggable_widgets.items():
            if widget and hasattr(widget, 'geometry'):
                geometry = widget.geometry()
                layout_config['widgets'][widget_name] = {
                    'x': geometry.x(),
                    'y': geometry.y(),
                    'width': geometry.width(),
                    'height': geometry.height(),
                    'visible': widget.isVisible()
                }
        
        # 保存到文件
        self.layouts[name] = layout_config
        self._save_layouts_to_file()
        
        return True
    
    def _save_layouts_to_file(self):
        """保存布局到文件"""
        self.save_layout_config()
    
    def create_layout_dialog(self):
        """创建布局设置对话框"""
        from PyQt6.QtWidgets import QMessageBox
        
        dialog = QDialog(self.main_window)
        dialog.setWindowTitle("布局设置")
        dialog.setFixedSize(500, 400)
        
        layout = QVBoxLayout()
        
        # 布局列表
        layout_group = QGroupBox("保存的布局")
        layout_group_layout = QVBoxLayout()
        
        self.layout_list = QListWidget()
        self.layout_list.addItems(list(self.layouts.keys()))
        layout_group_layout.addWidget(self.layout_list)
        
        # 布局操作按钮
        layout_btn_layout = QHBoxLayout()
        save_btn = QPushButton("保存当前布局")
        apply_btn = QPushButton("应用选中布局")
        delete_btn = QPushButton("删除选中布局")
        
        def save_current_layout():
            name = f"布局_{len(self.layouts) + 1}"
            self.save_layout(name)
            self.layout_list.addItem(name)
            QMessageBox.information(dialog, "成功", f"布局 '{name}' 已保存！")
        
        def apply_selected_layout():
            current_item = self.layout_list.currentItem()
            if current_item:
                layout_name = current_item.text()
                self.apply_layout(layout_name)
                QMessageBox.information(dialog, "成功", f"布局 '{layout_name}' 已应用！")
        
        def delete_selected_layout():
            current_item = self.layout_list.currentItem()
            if current_item:
                layout_name = current_item.text()
                if layout_name in self.layouts:
                    del self.layouts[layout_name]
                    self._save_layouts_to_file()
                    self.layout_list.takeItem(self.layout_list.row(current_item))
                    QMessageBox.information(dialog, "成功", f"布局 '{layout_name}' 已删除！")
        
        save_btn.clicked.connect(save_current_layout)
        apply_btn.clicked.connect(apply_selected_layout)
        delete_btn.clicked.connect(delete_selected_layout)
        
        layout_btn_layout.addWidget(save_btn)
        layout_btn_layout.addWidget(apply_btn)
        layout_btn_layout.addWidget(delete_btn)
        
        layout_group_layout.addLayout(layout_btn_layout)
        layout_group.setLayout(layout_group_layout)
        layout.addWidget(layout_group)
        
        # 对话框按钮
        button_layout = QHBoxLayout()
        ok_btn = QPushButton("确定")
        cancel_btn = QPushButton("取消")
        
        ok_btn.clicked.connect(dialog.accept)
        cancel_btn.clicked.connect(dialog.reject)
        
        button_layout.addWidget(ok_btn)
        button_layout.addWidget(cancel_btn)
        
        layout.addLayout(button_layout)
        dialog.setLayout(layout)
        
        return dialog